# _*_coding:utf-8 _*_
# @Time    :2019/11/5 16:53
# @Author  :Dapan
# @Email   :248312738@qq.com
import re
from ihome import redis_store, db
from ihome.models import User
from . import api
from flask import request,jsonify,current_app,session
from ihome.utils.response_code import RET
from sqlalchemy.exc import IntegrityError
from werkzeug.security import check_password_hash,generate_password_hash





@api.route('/users', methods=['POST'])
def register():
    """用户注册视图函数
    请求参数：手机号，手机验证码，密码，确认密码
    参数格式：json
    """
    # 获取请求的json数据，返回字典
    req_dict = request.get_json()

    mobile = req_dict.get('mobile')
    sms_code = req_dict.get('sms_code')
    password = req_dict.get('password')
    password2 = req_dict.get('password2')

    # 校验参数是否完整
    if not all([mobile,sms_code,password,password]):
        return jsonify(errno=RET.PARAMERR, errmsg='请求参数不完整')

    # 校验手机号格式是否正确
    if not re.match(r'1[34578]\d{9}',mobile):
        return jsonify(errno=RET.PARAMERR, errmsg='手机号格式错误')

    print(password, password2)
    # 校验确认密码是否正确
    if password != password2:
        return jsonify(errno=RET.DATAERR, errmsg='两次密码不一致，请检查后重试')

    # 获取redis中 保存的手机验证码
    try:
        real_sms_code = redis_store.get("sms_codes:%s" % mobile).decode()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="获取手机验证码验证失败，请刷新后重试")

    # 校验手机验证码是否过期
    if real_sms_code is None:
        return jsonify(errno=RET.NODATA, errmsg='手机验证码已过期，请稍后刷新重试')

    # 删除redis中保存的手机验证码，防止重复校验
    try:
        redis_store.delete("sms_codes:%s" % sms_code)
    except Exception as e:
        current_app.logger.error(e)

    # 校验手机验证码是否正确
    if real_sms_code != sms_code:
        return jsonify(errno=RET.DATAERR, errmsg='手机验证码验证失败，请稍后刷新重试')

    # 校验手机号是否已经注册
    # try:
    #     user = User.query.filter_by(mobile=mobile).first()
    # except Exception as e:
    #     current_app.logger.error(e)
    # else:
    #     if user is not None:
    #         表示数据库中查到了该手机 若注册，返回提示信息
            # return jsonify(errno=RET.DATAEXIST, errmsg="该手机号已经注册")

    # 保存注册信息到数据库
    user = User(name=mobile, mobile=mobile)
    # 将密码保存到数据库中
    # user.password = password
    user.password_hash = generate_password_hash(password)
    try:
        db.session.add(user)
        db.session.commit()
    except IntegrityError as e:
        current_app.logger.error(e)
        # 出现异常 回滚
        db.session.rollback()
        # 手机号字段设置了唯一，此异常表示数据库中手机号字段重复插入，即手机号已经注册过
        return jsonify(errno=RET.DATAEXIST, errmsg="该手机号已经注册")
    except Exception as e:
        # 捕获其他异常
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='查询数据失败')

    # 保存登录状态到session中
    session['name'] = mobile
    session['mobile'] = mobile
    session['user_id'] = user.id

    # 返回结果
    return jsonify(errno=RET.OK, errmsg='注册成功')


@api.route('/session', methods=['POST'])
def login():
    """
    用户登录
    用到参数：手机号，密码,json格式
    :return:
    """
    # 获取前端传过来的参数
    req_dict = request.get_json()
    mobile = req_dict.get('mobile')
    password = req_dict.get('password')
    # 校验参数是否完整
    if not all([mobile, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整，请重新登录')
    # 校验手机号格式是否正确
    if not re.match(r'1[34578]\d{9}', mobile):
        return jsonify(errno=RET.PARAMERR, errmsg='手机号格式错误')
    # 判断错误次数是否超过限制，如果超过限制，返回
    # redis记录 'access_nums_请求的ip'：次数限制
    user_ip = request.remote_addr   # 用户ip
    try:
        access_nums = redis_store.get('access_nums_%s'%user_ip)
    except Exception as e:
        current_app.logger.error(e)
    else:
        if access_nums is not None and int(access_nums) >= current_app.config.get('LOGIN_ERROR_MAX_TIMES'):
            return jsonify(errno=RET.REQERR, errmsg='登录错误次数过多，请稍后重试')
        # TODO 限制用户命名登录次数
    # 从数据库中根据手机号查询用户的数据对象
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='获取用户信息失败')
    # 校验登录密码是否正确
    print('user:',user)
    print(user.password_hash,password)
    if user is None or not check_password_hash(user.password_hash,password):
        # 如果验证失败记录错误次数
        try:
            redis_store.incr('access_nums_%s'%user_ip)
            redis_store.expire('access_nums_%s'%user_ip,current_app.config.get('LOGIN_ERROR_FORBID_TIME'))
        except Exception as e:
            current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='用户名或密码错误')
    # 通过校验后 保存登录状态到session中
    session['name'] = user.name
    session['mobile'] = user.mobile
    session['user_id'] = user.id

    return jsonify(errno=RET.OK, errmsg='登录成功')


@api.route('/session', methods=['GET'])
def check_login():
    '''检测登录状态'''
    name = session.get('name')
    if name is None:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    else:
        return jsonify(errno=RET.OK, errmsg='用户已登录',data={"name":name})


@api.route('/session', methods=['DELETE'])
def logout():
    """退出登录状态"""
    # 清除session数据
    session.clear()
    return jsonify(errno=RET.OK, errmsg='退出登录成功')



